package com.qq.多线程.线程池;

import java.util.concurrent.*;
/*

	
	ExecutorService的常用方法：
	void execute(Runnable command) 		执行任务/命令，没有返回值，一般用来执行 Runnable 任务
	Future<T> submit(Callable<T> task)	执行任务，返回未来任务对象获取线程结果，一般拿来执行 Callable 任务
	void shutdown() 					等任务执行完毕后关闭线程池
	List<Runnable> shutdownNow()		立刻关闭，停止正在执行的任务，并返回队列中未执行的任务	
	
	注：1.我们只需要创建任务对象交给线程池，它会自动帮我们分配或创建线程，所以继承Thread重写run方法的方式不可用了。
	   2.执行任务的流程：
	            线程池把任务分配给某一线程，任务对象的run方法代替了该线程的run方法
	            然后该线程自动调用start方法（内部调用run方法）启动线程。
       3.线程池的目的之一就是为了让里面的核心线程长久不死亡，所以关闭线程池在开发中不常用
    	  现在只能访问一次是因为现在系统没网页，以后有网页可以不断的访问系统
    	  就可以不断的用线程池里的线程处理用户请求，所以线程池是为以后准备的
	   
	   
    目标：自定义一个线程池对象，并测试其特性。
 */
public class ThreadPool_Test1 {
    public static void main(String[] args) {
        // 1、创建线程池对象
        /*
         public ThreadPoolExecutor(int corePoolSize,
                                 int maximumPoolSize,
                                 long keepAliveTime,
                                 TimeUnit unit,
                                 BlockingQueue<Runnable> workQueue,
                                 ThreadFactory threadFactory,
                                 RejectedExecutionHandler handler)
         */
    	
        ExecutorService pool = new ThreadPoolExecutor(3, 5 ,
                6, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5) ,
                Executors.defaultThreadFactory(),//可以不写，自动使用默认线程工厂
               new ThreadPoolExecutor.AbortPolicy());//可以不写，自动使用默认拒绝策略
        			//new了一个ThreadPoolExecutor的静态内部类对象（实现了RejectedExecutionHandler接口）
        //线程池参数:
        //核心线程3个、最大线程5个（临时线程2个）、临时线程存活时间六秒、任务队列5、默认的线程工厂、默认的拒绝策略。 
      
        //2、给10个任务交给线程池处理。（这里模拟是直接给线程池处理10个任务）
        Runnable target = new MyRunnable();
        Runnable target2 = new MyRunnable_E();
        
        //3个任务交给3个核心线程
        pool.execute(target);
        pool.execute(target);
        pool.execute(target2);//执行任务出现异常，线程被虚拟机挂了，会再创建一个核心线程thread-4
        						//异常最后抛给虚拟机后，他只会把出现异常的线程挂掉，并不是整个程序
        //5个任务在任务队列排队
        pool.execute(target);//分配任务给thread-4
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);//其实就是按照任务数来创建线程

        //2个任务交给创建的两个临时线程
        pool.execute(target);//核心线程都在忙，任务队列也满了，并且还可以创建临时线程
        pool.execute(target);//thread-6
        
        //第11个任务，拒绝策略被触发！！！使用CallerRunsPolicy()，main方法将亲自执行。
//        pool.execute(target);//核心线程和可创建的临时线程都在忙，任务队列也满了
//

        // 关闭线程池（开发中一般不会使用）。
        // pool.shutdownNow(); // 立即关闭，即使任务没有完成，并返回一个未完成任务集合
        pool.shutdown(); // 会等待全部任务执行完毕之后再关闭（建议使用的）
        

    }
}
